package com.dd.stack.se.stream.concurrent;
import org.openjdk.jol.info.ClassLayout;
import org.openjdk.jol.vm.VM;

import java.util.concurrent.TimeUnit;

/**
 * @Author liuxianmeng
 * @CreateTime 2025/9/6 9:13
 * @Description 演示synchronized多种锁状态升级过程
 *
 * 演进过程
 *      无锁状态 -> 偏向锁 -> 轻量级锁 -> 重量级锁 - - -> 无锁状态
 * 触发条件
 *      无锁状态 -> 偏向锁             当第一个线程访问同步块
 *      偏向锁 -> 轻量级锁             当第二个线程尝试获取锁（发生竞争）
 *      轻量级锁 -> 重量级锁           当自旋失败或多个线程竞争
 *      偏向锁 - - -> 无锁状态
 *      轻量级锁 - - -> 无锁状态
 *      重量级锁 - - -> 无锁状态
 * 注意事项
 *      偏向锁延迟：JVM默认延迟4秒后才会启用偏向锁，所以需要等待一段时间。
 *      JVM参数：可以通过JVM参数调整锁的行为，例如：
 *          -XX:-UseBiasedLocking：禁用偏向锁
 *          -XX:BiasedLockingStartupDelay=0：取消偏向锁延迟
 *      锁升级是不可逆的：一旦升级为更高级别的锁，不会降级（除非发生了STW，如GC）。
 *      实际输出可能不同：对象头的具体输出格式因JVM版本和架构而异。
 */
public class SynchronizedLocks {
    public static void main(String[] args) throws InterruptedException {
        // 打印JVM详细信息（包括字节序、对象头细节等）
        System.out.println(VM.current().details());

        // 创建一个简单的对象作为锁
        Object lock = new Object();

        // 1. 初始状态：无锁（可偏向）
        System.out.println("===== 初始状态（无锁可偏向） =====");
        System.out.println(ClassLayout.parseInstance(lock).toPrintable());
        /*===== 初始状态（无锁可偏向） =====
        java.lang.Object object internals:
        OFF  SZ   TYPE DESCRIPTION               VALUE
          0   8        (object header: mark)     0x0000000000000001 (non-biasable; age: 0)
          8   4        (object header: class)    0xf80001e5
         12   4        (object alignment gap)
        Instance size: 16 bytes
        Space losses: 0 bytes internal + 4 bytes external = 4 bytes total*/

        // 延迟一段时间，等待JVM默认开启偏向锁（默认延迟4秒）
        Thread.sleep(5000);

        // 再次创建一个对象，此时应该可偏向
        Object biasedLock = new Object();
        System.out.println("===== 可偏向状态（匿名偏向） =====");
        System.out.println(ClassLayout.parseInstance(biasedLock).toPrintable());
        /*===== 可偏向状态（匿名偏向） =====
        java.lang.Object object internals:
        OFF  SZ   TYPE DESCRIPTION               VALUE
          0   8        (object header: mark)     0x0000000000000005 (biasable; age: 0)
          8   4        (object header: class)    0xf80001e5
         12   4        (object alignment gap)
        Instance size: 16 bytes
        Space losses: 0 bytes internal + 4 bytes external = 4 bytes total*/

        // 2. 偏向锁
        System.out.println("===== 偏向锁 =====");
        synchronized (biasedLock) {
            System.out.println(ClassLayout.parseInstance(biasedLock).toPrintable());
            /*===== 偏向锁 =====
            java.lang.Object object internals:
            OFF  SZ   TYPE DESCRIPTION               VALUE
              0   8        (object header: mark)     0x0000026b88d83805 (biased: 0x000000009ae2360e; epoch: 0; age: 0)
              8   4        (object header: class)    0xf80001e5
             12   4        (object alignment gap)
            Instance size: 16 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total*/
        }

        // 3. 轻量级锁（模拟轻度竞争）
        System.out.println("===== 轻量级锁 =====");
        Thread t1 = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("线程1获取锁");
                    System.out.println(ClassLayout.parseInstance(lock).toPrintable());
                    /*===== 轻量级锁 =====
                    线程1获取锁
                    java.lang.Object object internals:
                    OFF  SZ   TYPE DESCRIPTION               VALUE
                      0   8        (object header: mark)     0x000000a2601ff138 (thin lock: 0x000000a2601ff138)
                      8   4        (object header: class)    0xf80001e5
                     12   4        (object alignment gap)
                    Instance size: 16 bytes
                    Space losses: 0 bytes internal + 4 bytes external = 4 bytes total*/
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread t2 = new Thread(() -> {
            System.out.println("线程2尝试获取锁");
            synchronized (lock) {
                System.out.println("线程2获取锁");
                System.out.println(ClassLayout.parseInstance(lock).toPrintable());
                /*线程2尝试获取锁
                线程2获取锁
                java.lang.Object object internals:
                OFF  SZ   TYPE DESCRIPTION               VALUE
                  0   8        (object header: mark)     0x0000026bb1e4f23a (fat lock: 0x0000026bb1e4f23a)
                  8   4        (object header: class)    0xf80001e5
                 12   4        (object alignment gap)
                Instance size: 16 bytes
                Space losses: 0 bytes internal + 4 bytes external = 4 bytes total*/
            }
        });

        t1.start();
        // 确保t1先启动
        Thread.sleep(100);
        t2.start();

        t1.join();
        t2.join();

        // 4. 重量级锁（模拟激烈竞争）
        System.out.println("===== 重量级锁 =====");
        // 创建10个线程激烈竞争锁
        for (int i = 0; i < 10; i++) {
            if(i == 8) {
                System.out.println("激烈竞争中锁状态：");
                System.out.println(ClassLayout.parseInstance(lock).toPrintable());
                /*===== 重量级锁 =====
                激烈竞争中锁状态：
                java.lang.Object object internals:
                OFF  SZ   TYPE DESCRIPTION               VALUE
                  0   8        (object header: mark)     0x00000200a4c1aa8a (fat lock: 0x00000200a4c1aa8a)
                  8   4        (object header: class)    0xf80001e5
                 12   4        (object alignment gap)
                Instance size: 16 bytes
                Space losses: 0 bytes internal + 4 bytes external = 4 bytes total*/
            }
            new Thread(() -> {
                synchronized (lock) {
                    try {
                        // 每个线程持有锁一段时间模拟业务操作
                        TimeUnit.MILLISECONDS.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }

        // 等待一段时间让竞争发生
        Thread.sleep(3000);

        // 查看最终锁状态（很可能已升级为重量级锁）
        System.out.println("激烈竞争后锁状态：");
        System.out.println(ClassLayout.parseInstance(lock).toPrintable());
        /*激烈竞争后锁状态：
        java.lang.Object object internals:
        OFF  SZ   TYPE DESCRIPTION               VALUE
          0   8        (object header: mark)     0x0000000000000001 (non-biasable; age: 0)
          8   4        (object header: class)    0xf80001e5
         12   4        (object alignment gap)
        Instance size: 16 bytes
        Space losses: 0 bytes internal + 4 bytes external = 4 bytes total*/
    }
}